% === Part two ===
\newpage
\chapter{Conception et développement de l'application}

\section{Savoir bien coder}

\subsection{Les bonnes pratiques}

\label{biencoder}

\subsubsection{Ne pas gaspiller son code}

C'est l'un des principes qui a fait le succès de la programmation objet : simplifier le code en le factorisant. Cependant, même en codant il faut essayer de pousser ce principe toujours un peu plus loin. De ce fait, dès qu'on est tenté de copier des lignes de codes à plusieurs endroits, il faut impérativement penser à factoriser. 

Cela permet de gagner plus de temps au moment du développement, mais aussi au moment du test, puisque le code n'en sera que plus clair et beaucoup plus simple à corriger.

L'utilisation de classes d'abstraction est ainsi recommandée. Même si, pour la plupart elles ne servent que de redirections vers les véritables méthodes qui exécutent tout le travail, elles permettent de concentrer toute l'exécution d'une fonctionnalité par le même point de passage. Celle-ci, une fois coupée du reste du code devient beaucoup plus facile à tester ou modifier. Un exemple d'une de ces classes est donné en annexe \ref{axsession}.

\subsubsection{Être bavard}

Commenter son code est un autre des point clés pour construire un bon code. Les tests et la maintenance seront forcément plus simples.

Certains diront qu'un bon code est un code qui n'a pas besoin de commentaires pour être compris, mais malgré la part de vérité dans cette affirmation, le code n'en sera que meilleur une fois commenté.

\subsubsection{Raconter une histoire}

Comme c'est toujours la phase de test qui pose le plus de problèmes, c'est toujours elle qu'il faut simplifier. En enregistrant les principales actions dans des fichiers ---~les fichiers de \textit{logs}~--- il est possible de retracer exactement ce qu'il s'est passé, et pourquoi ça n'a éventuellement pas marché. Néanmoins, lorsque l'application est utilisée par des centaines de visiteurs par jour, un tel système impliquerait des quantités colossales de données stockées. Pour éviter cela, il existe des niveaux de log plus ou moins importants suivant le type de message que l'on souhaite garder, et il suffit ensuite de filtrer les logs de niveaux faible. Voici une liste des niveaux définis sous Symfony, rangés par importance :

\begin{enumerate}
\item \textit{emerg} : quelque chose de très grave s'est produit et avec des conséquences ;
\item \textit{alert} : quelque chose de grave s'est produit et risque d'avoir des conséquences ;
\item \textit{crit} : quelque chose de grave a provoqué l'arrêt de l'application ;
\item \textit{err} : erreur dans le déroulement de l'application ;
\item \textit{warning} : quelque chose n'aurait pas dû se passer, stabilité de l'application non garantie ;
\item \textit{notice} : quelque chose d'étrange s'est passé, mais l'application continue ;
\item \textit{info} : les informations les plus utiles sur le déroulement ;
\item \textit{debug} : log basique, décrit le déroulement de l'application.
\end{enumerate}

Dans l'exemple \ref{codelog}, on voit bien les différents niveaux possibles. Pour faire de bon log, l'idée est de mettre un maximum d'informations lisibles en un minimum de place. L'utilisation de la constante PHP \verb?__METHOD__? est plus que recommandée car il est possible de retrouver ainsi exactement à quel endroit le code a été produit. La première ligne de l'exemple à ainsi été crée par la méthode \textit{doClean} de la classe \textit{ValidatorCodePostal}, et on y affiche également une variable calculée par cette méthode (qui cherche un lien entre une ville et un code postal).

\begin{lstlisting}[frame=lrtb, breaklines=true, caption={Logs typiques d'une application}, label=codelog]
Sep 08 17:00:27 symfony [debug] ValidatorCodePostal::doClean : AULHAT ST PRIVAT
Sep 08 17:00:27 symfony [debug] Souscripteur found
Sep 08 17:00:27 symfony [debug] tarificateurActions::executeSave/offre = 1
Sep 08 17:00:27 symfony [debug] EoviSouscripteurForm::setWidgetLoiMadelin
Sep 08 17:00:27 symfony [debug] Souscripteur ? 
Sep 08 17:00:27 symfony [debug] Conjoint (data = ) ? 
Sep 08 17:00:27 symfony [debug] Unset Loi Madelin
Sep 08 17:00:27 symfony [debug] methode de payment : cheque
Sep 08 17:00:27 symfony [info] {tarificateurActions} Forward to action "tarificateur/save"
Sep 08 17:00:27 symfony [info] {sfFilterChain} Executing filter "sfRenderingFilter"
Sep 08 17:00:27 symfony [info] {sfFilterChain} Executing filter "sfExecutionFilter"
Sep 08 17:00:27 symfony [info] {tarificateurActions} Call "tarificateurActions->executeSave()"

\end{lstlisting}

\subsection{Le kit du parfait développeur}

\label{outilsdev}

\subsubsection{Savoir gérer ses sources : \textit{Subversion}}

Subversion (abrégé en SVN) est un outil de gestion de code source. Il permet non seulement de partager un code commun sur lequel peuvent travailler de nombreux développeurs, mais aussi de disposer de l'image du code à différents stades du développement. C'est pour cela que l'on parle de \textit{gestionnaire de versions} : SVN fusionne le code de tous les contributeurs, et permet de revenir à une version antérieure de celui-ci si nécessaire.

\begin{figure}[!h]
\centering
\includegraphics[width=96mm]{images/principeSVN.png}
\caption[Principe de Subversion]{Principe de subversion avec les principales commandes.}
\label{fig:principesvn}
\end{figure}

Le principe de subversion est plutôt simple (voir figure \ref{fig:principesvn}) : le code est stocké initialement sur un \textit{dépôt\footnote{En anglais, on parle de \textit{repository}. Les deux termes sont couramment utilisés.}}. Les différents contributeurs importent la version initiale du code par une commande \textit{checkout}. Ils envoient ensuite, sur le dépôt, les modifications qu'ils apportent au code via des commandes \textit{commit}. Pour récupérer la dernière version du code sur sa propre machine, un contributeur effectue un \textit{update}.

SVN effectue automatiquement les fusions des fichiers quand deux contributeurs ont modifié le même fichier à des endroits différents. En cas de conflit (par exemple si un développeur a modifié les mêmes lignes qu'un autre), c'est au dernier contributeur qu'il revient de préciser quelle est la bonne version.

Il existe différents clients SVN : le plus simple est la ligne de commande, mais certains environnements intégrés de développement disposent d'un client graphique SVN intégré. Une documentation en anglais, plus que complète, est disponible en ligne (voir \cite{svndoc}).

\subsubsection{Utiliser au mieux les aides disponibles : L'IDE \textit{Netbeans}}

NetBeans est un environnement de développement intégré (IDE en anglais), placé en open source par Sun en juin 2000. NetBeans permet de supporter différents langages, comme Java, Python, C, C++, JavaScript, XML, Ruby, PHP et HTML. Il comprend toutes les caractéristiques d'un IDE moderne (éditeur en couleur, projets multi-langage, \textit{refactoring}\footnote{Théoriquement, le refactoring est le fait de pouvoir changer le nom d'une variable et que la modification s'effectue en cascade partout dans le projet}, éditeur graphique d'interfaces et de pages Web). Voici quelques unes des fonctionnalités les plus utiles :

\begin{description}
 \item[Accès direct à la Phpdoc du projet :] Il s'agit de tous les commentaires mis en début de classe ou fonction. Un code bien commenté devient ainsi plus clair et plus facile à utiliser. Quand l'accès à cette documentation est instantané, le gain est énorme.
 \item[Un connecteur SVN intégré :] Selon la personnalité du développeur, il peut ou non utiliser l'interface SVN intégrée nativement à Netbeans. Personnellement je ne l'utilisais que peu car l'utilisation du client en ligne de commande était amplement suffisante, beaucoup plus claire et rapide.
 \item[Navigation à l'intérieur du projet facilitée :] Il suffit de connaitre quelques raccourcis très utiles pour naviguer instantanément entre les fichiers. Par exemple, vous développez un petit algorithme dans une classe qui dépend d'une classe située dans une arborescence totalement différente. Il suffit de maintenir \textit{shift} et de cliquer sur le nom de la classe pour se rendre instantanément à sa déclaration. Extrêmement utile dans le cas de gros projets, mais cette fonctionnalité se perd parfois lorsque les règles d'accès aux méthodes et classes distantes sont court-circuitées\footnote{La méthode magique \lstinline!__toCall()! permet d'exécuter du code quand la méthode appelée n'a pas été trouvée. Il est possible de rediriger ainsi vers d'autres fonctions, et l'IDE devient incapable de suivre la trace.}.
  \item[Les groupes de projets :] Même aujourd'hui, je ne connais pas toutes les fonctionnalités de ce logiciel. Ainsi il y a peu de temps, nous avons découvert entre collègues une fonctionnalité très utile mais discrète pour créer des groupes de projets et changer de groupe en un clic. De cette façon, il devient très aisé de changer entre deux groupes régulièrement, sans risquer de confondre deux fichiers de deux groupes différents. Ce fût surtout très utile lorsqu'il a fallu en parallèle avoir un projet de recette et un projet de développement.

\end{description}

Malgré ces avantages, l'IDE souffre de quelques désagréments qui peuvent rendre certains développement pénible:

\begin{itemize}
\item il est plutôt lent et gourmand en ressources, notamment à l'ouverture ou pendant les opérations lourdes (actualisation de l'arborescence fichier par exemple) ;
\item il est parfois instable, ce qui rend la sauvegarde fréquente indispensable ; 
\item certaines fonctionnalités restent inaccessibles ou peu efficaces face aux fichiers PHP (comme le refactoring).
\end{itemize}

\subsubsection{La ligne de commande Unix, un allié indispensable}

La principale raison pour laquelle beaucoup de développeurs travaillent sous Linux n'est pas la gratuité du système (même si cette justification suffit à une grosse entreprise), mais principalement parce que ce système apporte de nombreux avantages pour programmer. En une ligne, il est possible de déplacer, copier, chercher, exécuter, ... et même tout à la fois.

La maitrise de cet outil est un plus qu'il ne faut pas négliger. Beaucoup de commandes fonctionnent suivant un système d'entrée sortie, et le \textit{pipe}, \og | \fg , permet de lier une sortie à une entrée . Par exemple la commande :

\verb?tail -f logs/errors.log | grep -v "info" | grep "mon_log"?

récupère en temps réel les messages écrits dans le fichier \textit{logs/errors.log}, filtre les lignes contenant \og \textit{info} \fg , et n'affiche que ceux contenant \og \textit{mon\_log} \fg .

De plus, Symfony l'utilise grandement pour beaucoup d'opération classiques de développement : créer des applications, des modules, gérer la base de données... Mais nous y reviendrons plus tard.

\subsubsection{Inspecter le résultat : Firebug}

Sans un outil efficace pour analyser le résultat produit par notre application, la développer serait une perte de temps. Heureusement un certain nombre de plugins des navigateurs actuels fournissent tout ce qu'il faut. Fans le cas de firefox, le plus répandu est Firebug (fig. \ref{firebug}). Il permet d'analyser le code source, de le modifier en temps réel, d'exécuter des commandes javascript, de parcourir le DOM\footnote{Le \textit{Document Object Model} est la représentation de la page générée par navigateur à partir du HTML source. Javascript est un langage spécialisé dans la manipulation du DOM, et malgré son manque de lisibilité, il est incroyablement puissant et rapide.}...

\begin{figure}[!h]
\centering
\includegraphics[width=13cm]{images/firebug.png}
\caption{Analyser une page web avec Firebug}
\label{firebug}
\end{figure} 

\section{Présentation du framework Symfony}

\subsection{Définition d'un framework, et présentation du modèle MVC}

\subsubsection{Le framework}

Le \textit{framework} permet de structurer son projet afin de rendre plus efficace le développement et la maintenance. Il découpe le projet en unités de travail plus petites et indépendantes, chacune ayant un rôle bien spécifique. Dans le cas idéal (et utopique), chaque partie ne dépendrait pas du reste de l'application, qui deviendrait totalement modulaire.

C'est le rôle du framework de gérer ensuite le déroulement de l'application via l'inversion de contrôle. Il sait ainsi quelle partie exécuter et à quel moment.

Un tel fonctionnement atténue grandement la complexité du développement et surtout augmente la facilité de débuggage. Ainsi le code est obligatoirement beaucoup plus lisible et logique, ce qui n'est pas forcément le cas si le développeur était peu expérimenté. De cette façon, même quelqu'un de nouveau sur le projet arriverait à s'y adapter beaucoup plus facilement puisqu'il connaîtrait d'avance l'architecture.

\subsubsection{Le schéma Modèle-Vue-Contrôleur : MVC}

La structure MVC est assez classique pour les projets informatiques actuels, notamment ceux disposant d'une interface homme-machine.

Un projet MVC est découpé en trois grandes parties : le contrôleur, la vue et le modèle :

\begin{itemize}
\item le modèle doit être indépendant de l'utilisateur dans le sens où il ne contient que des données pures ou des algorithmes génériques, il doit être réutilisable par d'autres applications ;
\item la vue est, à l'opposé, purement de la présentation, c'est l'interface homme-machine en soi ;
\item le contrôleur distribue les vues et gère les données du modèle, il supervise toute l'application.
\end{itemize}

\begin{figure}[!h]
\centering
\includegraphics[width=8cm]{images/mvc.png}
\caption{Les principaux composants d'une application MVC}
\end{figure} 

\subsection{L'architecture d'un projet Symfony}

\label{symfony}

Symfony est un framework open-source PHP en plein expansion. De plus en plus utilisé, il est souvent choisi de part sa souplesse et ses capacités. En effet, grâce à une interface par ligne de commande très puissante, il est possible d'obtenir très rapidement des résultats intéressants. Par exemple, la simple commande \verb?php symfony generate:project PROJECT_NAME? va générer toute l'architecture nécessaire au projet Symfony. Le premier gros atout de ce framework, est sa documentation en ligne (voir \cite{symfonydoc}). Nous ne détaillerons ici que le fonctionnement de symfony 1.4.

On a parlé plus haut du framework comme d'un outil de gestion de projet MVC. C’est bien sûr le cas de symfony qui, avec ses propres termes, utilise ce type d’architecture.


\subsubsection{Les actions}
Le contrôleur de l'application est représenté par un système d'actions. Basiqument, lors de l'appel d'une page, la requête va être d'abord transmise à un contrôleur frontal qui va l'analyser, puis la transmettre à l'action correspondante qui se charge d'effectuer des fonctionnalités spécifiques.

L'action se charge ainsi de construire la réponse en allant chercher les données du modèle et la structure de la vue, puis la renvoie à l'utilisateur.

Il est bien sûr possible de faire tout ce que fait une application classique, à savoir de la gestion de session, les redirections vers d'autres pages, la gestion de cookies...

\subsubsection{Le modèle}

Une action va avoir besoin de faire appel au modèle. Celui-ci se compose très souvent de classes directement liées aux tables en base de données. C'est à la charge de l’ORM (\textit{object-relationnal mapping}) d'assurer le transport des données entre l’application et la base.

Il sert de couche d'abstraction, ce qui fait que l'application devient totalement indépendante de la base. Celle-ci peut varier (MySQL, PostGre...) tant qu'elle est supportée par l'ORM.

Doctrine, l'ORM le plus souvent associé à Symfony, génère automatiquement des classes PHP
regroupant les principales fonctionnalités de base : des objets représentés dans les tables aux classes de génération de formulaires Symfony, en passant par des classes de filtrage, dans le cas d'un affichage en tableau du contenu de la base.

C'est un gain de temps énorme puisqu'en quelques minutes il est possible de faire apparaître quelques formulaires, de les personnaliser sans avoir à se soucier du fonctionnement interne. Ils sont construits de telle manière que la gestion des erreurs et la sauvegarde des données sont extrêmement simples.

De plus, Symfony, à l'aide de Doctrine dispose de son propre générateur d'interface d'administration. Elle est entièrement personnalisable et permet principalement un accès direct aux données en base. Ainsi il est possible de paramétrer l'interface utilisateur en arrière plan en utilisant exclusivement la base de données comme interface de configuration.

\subsubsection{Les templates}

Une fois la requête analysée il faut préparer la réponse en HTML. Cela se fait via des \textit{templates} qui correspondent à des fichiers PHP « inline » classiques dans lesquels on injecte un certain nombre de variables.

Afin de rester dans le cadre de la vue, il convient d'utiliser la syntaxe PHP alternative. Ainsi, on va préférer le listing \ref{htmltmp2} au listing \ref{htmltmp1}. 

\begin{lstlisting}[frame=L, caption={Template non propre}, label=htmltmp1]
<div>
  <?php if( isset($texte) )
    {
      echo $texte ;
    }  
  ?>
</div>
\end{lstlisting}

\begin{lstlisting}[frame=L,, caption={Template propre}, label=htmltmp2]
<div>
  <?php if( isset($texte) ): ?>
    <?php echo $texte ?>
  <?php endif ?>
</div>
\end{lstlisting}

Cette structure peut sembler plus lourde mais elle est nettement plus claire lorsqu’il s'agit de fichier volumineux. On distingue tout de suite les lignes PHP et les lignes HTML.

Un système de \textit{partials} permet de factoriser des morceaux de templates réutilisables dans d'autres pages. Il est possible aussi de créer et d’utiliser des \textit{helpers}, qui ne sont que de petites fonctions destinées à simplifier les parties en php, mais il ne faut jamais oublier que la vue n'est pas sensée contenir du code métier, mais principalement des fonctionnalités simple comme le parcours de liste ou quelques conditions.

\subsubsection{Les fichiers de configuration}
Un projet Symfony se décompose en plusieurs niveaux : le projet est constitué d’applications qui contiennent plusieurs modules. Certaines parties de la configuration sont globales (ex : accès à la base de donnée) d’autres sont plus spécifiques (constantes, etc...). Dans symfony tout peut être surchargé par niveau, du plus large au plus spécifique. On peut ainsi définir une classe ou une configuration pour le projet qui sera réécrit dans un module spécifique.

Symfony dispose d'un système de fichiers de configuration particulièrement performant basés sur le format YAML, dans le but d'allier la simplicité du fichier INI à la puissance des fichiers XML. Ce format permet de construire, tout comme le XML, des arbres mais en simplifiant grandement la syntaxe puisque seule l'indentation permet de reconnaitre les nœuds :

\begin{verbatim}
Root:
  Element1:
    Element1_1: Valeur 1
    Element1_2: "Valeur 2"
  Element2: Valeur 3
\end{verbatim}

Un bonne partie de la configuration du projet passe par ces fichiers dont voici quelques uns parmi les principaux :
\begin{description}
\item[databases.yml :] définit les codes d'accès à la base de données, et éventuellement l’ORM à utiliser.
\item[app.yml :] définit les constantes du projet, avec la possibilité de les trier par environnement d'exécution de l'application. L'environnement est un outil puissant qui permet de passer d'une configuration à une autre sans changer le code.
\item[view.yml :] définit un certain nombre de paramètres pour la construction de la vue comme les \textit{headers HTTP}, les javascripts à inclure ou les feuilles de style. Il est possible de le paramétrer en fonction de l'action qui va être exécutée.
\item[routing.yml :] définit le système d'analyse des url. C'est un système de réécriture d'URL très puissant qui permet d'encoder et décoder des URL suivant les paramètres disponibles, afin d'obtenir des URL plus compréhensibles. Par exemple, la route :
\begin{verbatim}
show_customer_profile:
  url: /votre_profil/:id/:nom/:prenom
  params:
    module: customer
    action: show
\end{verbatim}
donnera des url du type : \verb?/votre_profil/2341/georges/abitbol? et pointera sur
l’action \textit{show} du module \textit{customer}, laquelle aura accès aux paramètres \textit{id}, \textit{nom} et \textit{prenom}.
\end{description}

\section{La gestion de formulaires avec Symfony}

La gestion des formulaires est quelque chose de très bien implémentée dans Symfony, représentée par la classe de base \textit{sfForm}. Tant que l'on reste dans des formulaires classique (contact, QCM, ...), l'utilisation de cette classe est vraiment très simple.

Comme beaucoup de choses dans Symfony, il est possible de surcharger les classes de base pour modifier le comportement initial. De cette façon, il est possible d'obtenir des comportements beaucoup plus complexes avec cette même classe de base.

\subsection{Principes de bases}

Une classe formulaire étend forcément \textit{sfFrom} et permet de définir les champs (\textit{widgets}) utilisés dans l'affichage, ainsi que les validateurs (\textit{validators}) liés aux données qui seront postées par un utilisateur. Basiquement, une classe formulaire ressemble ainsi au listing \ref{formcontact}.

\begin{lstlisting}[frame=L,breaklines=true,caption={Formulaire de contact}, label=formcontact]
class ContactForm extends sfForm
{
  protected static $subjects = array('Subject A', 'Subject B', 'Subject C');
 
  public function configure()
  {
    $this->setWidgets(array(
      'name'    => new sfWidgetFormInputText(),
      'email'   => new sfWidgetFormInput(array('default' => 'me@example.com')),
      'subject' => new sfWidgetFormChoice(array('choices' => array('Subject A', 'Subject B', 'Subject C'))),
      'message' => new sfWidgetFormTextarea(),
    ));
    $this->setValidators(array(
      'name'    => new sfValidatorString(),
      'email'   => new sfValidatorEmail(),
      'subject' => new sfValidatorString(),
      'message' => new sfValidatorString(array('min_length' => 4))
    ));
    $this->setDefaults(array(
      'email' => 'me@example.com'
    ));
  }
}
\end{lstlisting}

\begin{figure}[!h]
\centering
\includegraphics[width=4cm]{images/exformcontact.png}
\caption{Formulaire de contact}
\end{figure} 

\subsection{\textit{sfForm} et Doctrine}

Doctrine, l'ORM principal de Symfony, s'est très bien adapté à ces composants puisqu'il est capable de générer automatiquement les classes \textit{Form} de base représentants tous les objets de la table, avec des champs et des validateurs correspondants aux types de données.

Même si elles sont rarement utilisées à l'état brut, ces classes générées sont très utiles comme outil de travail de base. Elles étendent une autre classe de base intermédiaire, spécifique à l'objet qu'elles représentent toujours, qui contient toutes les définitions des champs et des validateurs par défaut. Ainsi, si la structure de la base change, ces données par défaut changent, et le formulaire s'adapte.

\subsection{Fonctionnalités avancées}

\subsubsection{Les formulaires embarqués}

Parfois, il peut être intéressant de fusionner plusieurs formulaires, à la base relativement indépendants. Pour cela, sfForm dispose d'un mécanisme intégré qui permet cette fusion partielle : il s'agit des formulaires embarqués (ou \og \textit{embedded forms} \fg{} en anglais).

Une fois un formulaire embarqué, sfForm importe tous ses champs et validateurs. Cependant, il faut bien se rendre compte que la fusion s'arrête là, car sfForm utilise ses propres fonctions de parcours des validateurs plutôt que celles de la classe embarquée. Ainsi, dans le cas de traitements spéciaux, il faut bien faire attention à les réaliser dans la classe qu'il faut.

\subsubsection{La dynamisation du formulaire avec des appels \textit{AJAX}}

AJAX est l'acronyme de \og \textit{Asynchronous Javascript And XML} \fg{}. Ce n'es pas un langage, mais une technique qui permet d'importer des données dans une page via javascript. De cette façon il est possible d'importer dans un formulaire des données comme par exemple des message d'erreurs lors de la validation dynamique des champs, ou alors d'importer directement plusieurs champs identiques\footnote{Dans ce dernier cas, pour des formulaires embarqués, il existe un petit bug Symfony qui gène la création des champs. Pour y remédier, il faut embarquer les \textit{n} formulaires enfants dans un premier formulaire vide, puis embarquer ce dernier dans le formulaire parent.} (pour \textit{n} enfants d'un souscripteur par exemple). Il suffit ensuite d'importer convenablement ces éléments dans la page. 

\subsubsection{La création d'un tunnel et les sessions}

Pour notre application, il faut utiliser un formulaire sur plusieurs pages. Rien n'est prévu pour cela dans Symfony, mais il suffit d'une petite astuce pour y arriver. En créant une méthode \verb?getFields()? par exemple, il est possible de donner plusieurs rendus différents d'une même classe.

La classe peut en effet contenir autant de couples champs-validateurs que désiré, tant qu'à la fin ceux ci sont filtrés. Il suffit ensuite de garder les données tout au long du tunnel, pour ne les sauvegarder qu'à la fin. La session est toute indiquée pour la conservation de ces données (voir annexe \ref{axsession}).

\section{Fonctionnement global du tarificateur}

\subsubsection{L'intégration à ezPublish}

Le projet étant séparé en deux parties, il a fallu trouver un moyen de les lier. Pour cela, une intégration AJAX nous a paru être la meilleure idée, car elle est totalement adaptable. Ainsi, nous avons pu rajouter un autre bloc mineur Symfony dans une zone totalement séparée de la zone de base, et la communication eZ/Symfony est devenue beaucoup plus simple (passage de paramètres dans l'appel).

\subsection{Contrôleur}

La première couche la plus importante est le contr\^oleur, puisque c'est le point d'entrée de l'application. Puisque le chargement se fait toujours sur la même page, c'est une action frontale qui va décider sur quelle action rediriger. C'est elle qui sert d'interface entre eZ et Symfony.

Ensuite viennent les 5 principales actions, qui représentent chacune une page. Comme beaucoup de code se ressemble entre ces action, j'ai créé des méthodes de base exécutant les requêtes nécessaires. Elles sont paramétrables via un unique tableau de paramètres (non-obligatoires, les valeurs par défaut existent). l'algorithme global est le suivant :

\begin{itemize}
\item Si la requête HTTP est un \textit{POST} alors :
\begin{itemize}
\item valider le formulaire, et s'il est correct 
\begin{itemize}
\item enregistrer les données ;
\item passer à l'étape suivante ;
\end{itemize} 
\item sinon afficher les erreurs.
\end{itemize}
\item Si c'est un \textit{GET} :
\begin{itemize}
\item afficher le formulaire avec les données éventuellement déjà remplies.
\end{itemize}
\end{itemize} 

\subsection{Gestion du formulaire}

Toute la gestion du formulaire passe par la m\^eme classe : EoviSouscripteurForm qui étend entre autres, sfForm. Elles possèdent deux méthodes principales dont voici le but :

\begin{description}
\item[\verb?EoviSouscripteurForm::configure()? :] Elle définit les classes \og \textit{Widget} \fg{} des champs à utiliser et les classes \og \textit{Validator} \fg{} correspondantes. Il est possible de définir les champs pour toutes les étapes dans cette fonction, pour ensuite les filtrer via la méthode \verb?useFields()?. C'est ici aussi que l'on peut insérer les labels, et messages d'erreurs personnalisés pour chaque champ. Afin d'augmenter la lisibilité, ces textes ont été déportés dans un fichier de configuration.
\item[\verb?EoviSouscripteurForm::bind()? :] Cette méthode valide un tableau de valeurs entrées dans le formulaire. Elle va chercher les validateurs instanciés par \verb?configure()? pour tester les valeurs une par une, et éventuellement les mettre en forme. Il est important que les valeurs fournies correspondent exactement aux validateurs créés sinon le formulaire ne sera pas valide. Cette contrainte m'a posé beaucoup de difficultés lors de l'utilisation de champs dynamiques (enfants et conjoint) et pour y remédier j'ai du analyser le fonctionnement de sfForm en profondeur pour savoir à quel moment redéfinir les validateurs nécessaires.
\end{description}

\subsection{Gestion des données}

Il existe deux niveaux de données : les données \og courantes \fg{} et les données \og archivées \fg{} :

\begin{description}
\item[Les données courantes] représentent les données au moment où elles sont envoyées à Symfony par un utilisateur. Afin de les conserver entre les étapes (dans le cas d'un retour en arrière), il convient de les stocker en session\footnote{cf annexe \ref{axsession}}. De cette façon elles sont rapidement accessibles à tout moment.
\item[Les données archivées] sont les données stockées en base mysql. Elles doivent l'être au moment de la création d'un devis et au moment de la souscription finale. De cette façon Eovi conserve la trace des visiteurs qui ont juste été intéressés par un devis rapide et de ceux qui ont réellement souscrit à la garantie proposé.
\end{description}

\subsection{Exports}

Les exports sont accessibles via l'interface d'administration. Ils sont assez simples à créer grâce à Doctrine qui permet de générer des requêtes en base assez simplement et de façon sûre. Le reste n'est que de la mise en page des informations demandées.


